﻿using System.Windows;
using System.Windows.Input;
using XEvolve.Core.Runtime;
using ICommandSource=XEvolve.Presentation.Input.Internal.ICommandSource;

namespace XEvolve.Presentation
{
    public static class Navigation
    {
        private const string SINGLETON_VIEW = "SINGLETON_VIEW";

        public static DependencyProperty DestinationProperty = DependencyProperty.RegisterAttached("Destination",
                                                                                                   typeof(object),
                                                                                                   typeof(Navigation), new FrameworkPropertyMetadata(OnNavigationChanged));

        public static void SetDestination(DependencyObject o, object value)
        {
            o.SetValue(DestinationProperty, value);
        }

        public static object GetDestination(DependencyObject o)
        {
            return o.GetValue(DestinationProperty);
        }

        public static DependencyProperty ParameterProperty = DependencyProperty.RegisterAttached("Parameter",
                                                                                   typeof(object),
                                                                                   typeof(Navigation), new FrameworkPropertyMetadata(OnNavigationChanged));

        public static void SetParameter(DependencyObject o, object value)
        {
            o.SetValue(ParameterProperty, value);
        }

        public static object GetParameter(DependencyObject o)
        {
            return o.GetValue(ParameterProperty);
        }

        public static DependencyProperty ViewInstanceIdProperty = DependencyProperty.RegisterAttached("ViewInstanceId",
                                                                                           typeof(object),
                                                                                           typeof(Navigation), new FrameworkPropertyMetadata(SINGLETON_VIEW, OnNavigationChanged));

        public static void SetViewInstanceId(DependencyObject o, object value)
        {
            o.SetValue(ViewInstanceIdProperty, value);
        }

        public static object GetViewInstanceId(DependencyObject o)
        {
            return o.GetValue(ViewInstanceIdProperty);
        }


        private static void OnNavigationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var destination = GetDestination(d);
            var commandSource = d.GetAdapter<ICommandSource>();            
            if (commandSource != null && destination != null)
            {
                commandSource.SetCommand(NavigateTo);
                commandSource.SetCommandParameter(new NavigationParameter(destination, GetViewInstanceId(d), GetParameter(d)));
            }
        }

        public static RoutedEvent InitializeViewEvent = EventManager.RegisterRoutedEvent("InitializeView", RoutingStrategy.Direct, typeof(InitializeViewEventHandler), typeof(Navigation));


        public static void AddInitializeViewHandler(DependencyObject o, InitializeViewEventHandler handler)
        {
            ((UIElement)o).AddHandler(InitializeViewEvent, handler);
        }
        public static void RemoveInitializeViewHandler(DependencyObject o, InitializeViewEventHandler handler)
        {
            ((UIElement)o).RemoveHandler(InitializeViewEvent, handler);
        }

        public static RoutedCommand NavigateTo = new RoutedCommand("NavigateTo", typeof(Navigation));

        public class NavigationParameter
        {
            public object ViewId { get; private set; }
            public object ViewInstanceId { get; private set; }
            public object Parameter { get; private set; }

            public NavigationParameter(object viewId, object viewInstanceId, object parameter)
            {
                
                ViewId = viewId;
                ViewInstanceId = viewInstanceId;
                Parameter = parameter;
            }
        }
    }

    public delegate void InitializeViewEventHandler(object sender, InitializeViewEventArgs e);

    public class InitializeViewEventArgs : RoutedEventArgs
    {
        public object Parameter { get; private set; }

        public InitializeViewEventArgs(object parameters) : base(Navigation.InitializeViewEvent)
        {
            Parameter = parameters;
        }
    }
}
